{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 装饰器与lru_cache"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import time\n",
    "import functools\n",
    "\n",
    "def clock(func):\n",
    "    @functools.wraps(func)\n",
    "    def clocked(*args, **kwargs):\n",
    "        t0 = time.time()\n",
    "        result = func(*args, **kwargs)\n",
    "        elapsed = time.time() - t0\n",
    "        name = func.__name__\n",
    "        arg_lst = []\n",
    "        if args:\n",
    "            arg_lst.append(', '.join(repr(arg) for arg in args))\n",
    "        if kwargs:\n",
    "            pairs = ['%s=%r' % (k, w) for k, w in sorted(kwargs.items())]\n",
    "            arg_lst.append(', '.join(pairs))\n",
    "        arg_str = ', '.join(arg_lst)\n",
    "        print('[%0.8fs] %s(%s) -> %r ' % (elapsed, name, arg_str, result))\n",
    "        return result\n",
    "    return clocked"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "@clock\n",
    "@functools.lru_cache()\n",
    "def fibonacci(n):\n",
    "    if n < 2:\n",
    "        return n\n",
    "    else:\n",
    "        return fibonacci(n - 2) + fibonacci(n - 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0.00000000s] fibonacci(0) -> 0 \n",
      "[0.00000000s] fibonacci(1) -> 1 \n",
      "[0.00000000s] fibonacci(2) -> 1 \n",
      "[0.00000000s] fibonacci(1) -> 1 \n",
      "[0.00000000s] fibonacci(2) -> 1 \n",
      "[0.00000000s] fibonacci(3) -> 2 \n",
      "[0.00000000s] fibonacci(4) -> 3 \n",
      "[0.00000000s] fibonacci(3) -> 2 \n",
      "[0.00000000s] fibonacci(4) -> 3 \n",
      "[0.00000000s] fibonacci(5) -> 5 \n",
      "[0.00000000s] fibonacci(6) -> 8 \n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "8"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fibonacci(6)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 分派函数\n",
    "python不支持重载方法（也不必要，可变参数类型，可变参数个数）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "from functools import singledispatch\n",
    "from collections import abc\n",
    "import numbers\n",
    "import html\n",
    "\n",
    "@singledispatch\n",
    "def htmlize(obj):\n",
    "    content = html.escape(repr(obj))\n",
    "    return '<pre>{}</pre>'.format(content)\n",
    "\n",
    "@htmlize.register(str)\n",
    "def _(text):\n",
    "    content = html.escape(text).replace('\\n', '<br>\\n')\n",
    "    return '<p>{0}</p>'.format(content)\n",
    "\n",
    "@htmlize.register(numbers.Integral)\n",
    "def _(n):\n",
    "    return '<pre>{0} (0x{0:x})</pre>'.format(n)\n",
    "\n",
    "@htmlize.register(tuple)\n",
    "@htmlize.register(abc.MutableSequence)\n",
    "def _(seq):\n",
    "    inner = '</li>\\n<li>'.join(htmlize(item) for item in seq)\n",
    "    return '<ul>\\n<li>' + inner + '</li>\\n</ul>'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<ul>\n",
      "<li><pre>1 (0x1)</pre></li>\n",
      "<li><pre>2 (0x2)</pre></li>\n",
      "<li><pre>{3}</pre></li>\n",
      "</ul>\n"
     ]
    }
   ],
   "source": [
    "ret = htmlize([1,2,{3}])\n",
    "print(ret)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
